from contextlib import asynccontextmanager

import uvicorn
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from fastapi import FastAPI, Depends, Request
from fastapi.exceptions import RequestValidationError
from loguru import logger
import sys
import os
from sqlalchemy.exc import SQLAlchemyError
from starlette.middleware.cors import CORSMiddleware
from config.Database import get_db, engine, Base
from controllers.Notification import router as notification_router
from controllers.ActivityController import router as activity_router
from controllers.NewInfoPushController import router as new_info_push_router
from controllers.FileController import router as fileController_router
from controllers.AccountUsageController import router as accountUsage_router
from controllers.UserController import router as user_router
from middleware.ExceptionHandler import validation_exception_handler, sqlalchemy_exception_handler, http_exception_handler
from scheduler.AutoSignApplyScheduler import scan_and_schedule_sign_tasks
import logging

from scheduler.ActivityScheduler import apply_job
from scheduler.NewInfoPushScheduler import check_new_activities

# 创建日志目录
log_path = "logs"
os.makedirs(log_path, exist_ok=True)

# 移除默认的日志处理器
logger.remove()

# 添加控制台处理器 - 只显示INFO及以上级别
logger.add(sys.stderr, level="INFO", format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>")

# 添加INFO级别日志文件处理器 - 按天轮转，保留7天
logger.add(
    os.path.join(log_path, "info_{time:YYYY-MM-DD}.log"), 
    level="INFO",
    rotation="00:00",  # 每天午夜轮转
    retention="7 days",  # 保留7天
    format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
    filter=lambda record: record["level"].name == "INFO"
)

# 添加WARNING级别日志文件处理器
logger.add(
    os.path.join(log_path, "warning_{time:YYYY-MM-DD}.log"), 
    level="WARNING",
    rotation="00:00",
    retention="7 days",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
    filter=lambda record: record["level"].name == "WARNING"
)

# 添加ERROR级别日志文件处理器
logger.add(
    os.path.join(log_path, "error_{time:YYYY-MM-DD}.log"), 
    level="ERROR",
    rotation="00:00",
    retention="30 days",  # 错误日志保留更长时间
    format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
    filter=lambda record: record["level"].name in ["ERROR", "CRITICAL"]
)

# 添加所有日志的完整记录
logger.add(
    os.path.join(log_path, "all_{time:YYYY-MM-DD}.log"), 
    level="DEBUG",
    rotation="00:00",
    retention="3 days",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}"
)

# 显示 DEBUG 级别的日志（包括执行的具体 SQL）
logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)

# 使用 AsyncIOScheduler 替代 BackgroundScheduler
scheduler = AsyncIOScheduler()

@asynccontextmanager
async def lifespan(app: FastAPI):
    # 启动时执行的代码
    Base.metadata.create_all(bind=engine)
    
    # 启动定时任务 - 使用异步调度器
    scheduler.add_job(apply_job, 'interval', seconds=2,max_instances=2,misfire_grace_time=3)
    scheduler.add_job(check_new_activities, 'interval', seconds=11,max_instances=2,misfire_grace_time=3)
    scheduler.add_job(scan_and_schedule_sign_tasks, 'interval', seconds=12,max_instances=2,misfire_grace_time=3)
    scheduler.start()
    logger.info("定时任务已启动")

    yield
    
    # 关闭时执行的代码
    scheduler.shutdown()
    logger.info("定时任务已关闭")
    logger.info("数据库连接已关闭")

# 创建FastAPI应用，使用 lifespan 参数
app = FastAPI(title="TwoClass API", lifespan=lifespan)
app.add_middleware(
        CORSMiddleware,
        allow_origins=['*'],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )

# 注册异常处理器
app.add_exception_handler(RequestValidationError, validation_exception_handler)
app.add_exception_handler(SQLAlchemyError, sqlalchemy_exception_handler)
app.add_exception_handler(Exception, http_exception_handler)

# 注册路由
app.include_router(notification_router)
app.include_router(activity_router)
app.include_router(fileController_router)
app.include_router(new_info_push_router)
app.include_router(accountUsage_router)
app.include_router(user_router)


if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=48080, reload=True)



